# SingleTablePolymorphism.java

    package org.codefilarete.stalactite.engine.configurer.model;

    import java.util.Map;
    import java.util.Set;

    import org.codefilarete.stalactite.sql.ddl.structure.Column;
    import org.codefilarete.stalactite.sql.ddl.structure.Table;
    import org.codefilarete.tool.collection.KeepOrderMap;
    import org.codefilarete.tool.collection.KeepOrderSet;

    /**
     * All subclasses share the parent table. A discriminator column distinguishes rows by their runtime type.
     *
     * @param <C> parent entity type
     * @param <I> identifier type
     * @param <D> discriminator value type (e.g. {@link String}, {@link Integer})
     * @param <T> the shared table type
     */
    public class SingleTablePolymorphism<C, I, D, T extends Table<T>> implements EntityPolymorphism<C, I> {

        /** The shared table (same as rootEntity.getTable()) */
        private final Column<T, D> discriminatorColumn;

    	/** Sub-entities keyed by their discriminator value. Insertion order is preserved for test stability. */
    	private final Map<D, Mapping<? extends C, T>> subEntitiesPerDiscriminator = new KeepOrderMap<>();

    	public SingleTablePolymorphism(Column<T, D> discriminatorColumn) {
    		this.discriminatorColumn = discriminatorColumn;
    	}

    	public Column<T, D> getDiscriminatorColumn() {
    		return discriminatorColumn;
    	}

    	public void addSubEntity(D discriminatorValue, Mapping<? extends C, T> subEntity) {
    		subEntitiesPerDiscriminator.put(discriminatorValue, subEntity);
    	}

    	public Map<D, Mapping<? extends C, T>> getSubEntitiesPerDiscriminator() {
    		return subEntitiesPerDiscriminator;
    	}

    	/** Returns the discriminator value associated with the given subclass type. */
    	public D getDiscriminatorValue(Class<? extends C> subType) {
    		return subEntitiesPerDiscriminator.entrySet().stream()
    				.filter(e -> e.getValue().getEntityType().equals(subType))
    				.map(Map.Entry::getKey)
    				.findFirst()
    				.orElseThrow(() -> new IllegalArgumentException("No discriminator value found for type: " + subType));
    	}

    	@Override
    	public Set<Mapping<? extends C, ?>> getSubEntities() {
    		return new KeepOrderSet<>(subEntitiesPerDiscriminator.values());
    	}
    }